#pragma once
#ifndef RTSP_H
#define RTSP_H
#include <QByteArray>
#include <QString>
#include <QtEndian>

#include "Sdp.h"
namespace RTSP
{
    enum Method
    {
        OPTIONS = 0,
        DESCRIBE,
        SETUP,
        PLAY,
        OVER_PLAY,
        TEARDOWN
    };

    enum SETUP_MODE
    {
        NONE,
        TCP,
        UDP,
    };

    QString getMethodName(RTSP::Method method);

    struct Interleaved
    {
        uint8_t dollar_sign; // 0x24 $
        uint8_t channel;     // 通常: 0x00 RTP, 0x01 RTCP
        uint16_t length;

        inline uint16_t getLength() { return qFromBigEndian(length); }
    };

}

// 从raply中解析出的数据
struct RaplyData
{
    int ResponseStateCode;
    int ContentLength{200};
    // int Cseq;
    // QByteArray SessionID; // rtsp请求发起后，服务端返回唯一标识
    void clear()
    {
        ResponseStateCode = 0;
        ContentLength = 0;
        // Cseq = 0;
        // SessionID.clear();
    }
};

class RtspManager
{
private:
    char m_bufSnd[1024] = {0};

    QByteArray m_rtspUrl;
    QByteArray m_userAgent = "viki_RTSPClient";
    uint16_t port_1 = 55555;
    uint16_t port_2 = 55556;

    uint16_t server_port_1 = 0;
    uint16_t server_port_2 = 0;

    // std::unique_ptr<RaplyData> tmpData{nullptr}; // 当前请求的raply数据

    RaplyData curRaplyData;

    QByteArray m_sessionMsg;

    int m_sendCseq{1}; // 每次会话的Cseq进度
    RTSP::Method nextMethod = RTSP::OPTIONS;

    SdpTrack *curTrack{nullptr}; // 当前正在处理的track
    Sdp m_sdp;

    RTSP::SETUP_MODE setupMode = RTSP::NONE;
    void writeSdp(const QByteArray &sdp);

    void parseReply(const QByteArray &reply, RaplyData &data);
    QByteArray getCmd(int responseCode);
    QByteArray getNextCmd(RTSP::Method &nextMethod);

    QByteArray getTcpTransport(int trackId);
    QByteArray getUdpTransport(uint16_t client_port_1, uint16_t client_port_2);

    QByteArray getCmdOPTIONS();
    QByteArray getCmdDESCRIBE();
    QByteArray getCmdSETUP(const QByteArray &control, const QByteArray &transport);
    QByteArray getCmdPLAY(/*QByteArray range*/);
    QByteArray getCmdTEARDOWN();

public:
    RtspManager() {}

    QByteArray parseReplyAndGetCmd(const QByteArray &reply);

    inline QByteArray getStartCmd() { return getCmd(200); }
    inline QByteArray getEndCmd() { return getCmdTEARDOWN(); }

    void setRtspUrl(const QByteArray &url);
    inline QByteArray getRtspUrl() { return m_rtspUrl; }

    inline RTSP::Method getNextMethod() { return nextMethod; }
    inline QString getNextMethodName() { return RTSP::getMethodName(nextMethod); }
    inline const RaplyData &getCurRaplyData() { return curRaplyData; }
    inline RTSP::SETUP_MODE getSetupMode() { return setupMode; }

    inline uint16_t getPort_1() { return port_1; }
    inline uint16_t getPort_2() { return port_2; }
    inline void setPort_1(uint16_t port) { port_1 = port; }
    inline void setPort_2(uint16_t port) { port_2 = port; }

    inline Sdp *getSdp() { return &m_sdp; }
};

#endif